/*  Army Editor for yALB - Yet Another List Builder (roster Editor for Wargames/tabletop games).
    Copyright (C) 2011  Daniel Ricardo Castro Alvarado

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.*/

#include "inheritedmanager.h"
#include "newtreewidget.h"
#include <QStringList>
#include <QDebug>
#include <QMessageBox>

#define CATEGORY_ROW 0
#define ITEMS_ROW 1
#define OPTIONS_ROW 2
#define GLOBAL_TEXTS_ROW 3


InheritedManager::InheritedManager(QTreeWidget *inheritTree, QTreeWidget *unitTree, QTreeWidget *itemTree,
                                   QTreeWidget *optionTree, StructManager *inheritanceManager, QWidget *parent) : StructManager(parent) {
    this->inheritTree = inheritTree;
    this->unitTree = unitTree;
    this->itemTree = itemTree;
    this->optionTree = optionTree;
    this->optionCategories = NULL;
    this->itemCategories = NULL;
    this->unitCategories = NULL;
    this->inheritedCategoriesData = NULL;
    this->inheritedItemsData = NULL;
    this->inheritedOptionsData = NULL;
    this->inheritanceManager = inheritanceManager;
    this->parent = parent;
    this->unitTree->resizeColumnToContents(1); // Resize "Cost" column to contents
}

bool InheritedManager::addCategory(const GameCategory &category, const QString &key) {
    if(inheritTree && unitTree && itemTree && optionTree && inheritedCategoriesData &&
            itemCategories && optionCategories && unitCategories && StructManager::addCategory(category, key)) {
        NewTreeWidgetItem *item = new NewTreeWidgetItem(inheritTree->topLevelItem(CATEGORY_ROW)->child(category.type), QStringList(category.getName()));
        item->setData(0, Qt::UserRole, QVariant(key));
        item->setFlags(item->flags() & ~Qt::ItemIsUserCheckable); // User can't change the state
        item->setCheckState(0, Qt::Checked);
        if(category.type == GameCategory::CategoryOfUnits) {
            QTreeWidgetItem *catItem = new QTreeWidgetItem(unitTree, QStringList(category.getName()));
            catItem->setData(0, Qt::UserRole, QVariant(key));
            unitTree->expandItem(catItem);

            // Add the category to the combo box so we can choose it

            unitCategories->addItem(category.getName(), QVariant(key));
        } else if(category.type == GameCategory::CategoryOfItems) {

            // Add a top level item for new items
            QTreeWidgetItem *catItem = new QTreeWidgetItem(itemTree, QStringList(category.getName()));
            catItem->setData(0, Qt::UserRole, QVariant(key));
            itemTree->expandItem(catItem);

            // Add a top level item for inherited items
            catItem = new NewTreeWidgetItem(inheritTree->topLevelItem(ITEMS_ROW), QStringList(category.getName()));
            // Allowing Tristate, this item will automatically change its state acording to its childs
            catItem->setFlags(catItem->flags() | Qt::ItemIsTristate);
            catItem->setData(0, Qt::UserRole, QVariant(key));
            catItem->setCheckState(0, Qt::Unchecked); // Make the checkbox visible by setting the default value
            inheritTree->expandItem(catItem);

            // Add the category to the combo box so we can choose it
            itemCategories->addItem(category.getName(), QVariant(key));
        } else if(category.type == GameCategory::CategoryOfOptions) {

            // Add a top level item for new options
            QTreeWidgetItem *catItem = new QTreeWidgetItem(optionTree, QStringList(category.getName()));
            catItem->setData(0, Qt::UserRole, QVariant(key));
            optionTree->expandItem(catItem);

            // Add a top level item for inherited options
            catItem = new NewTreeWidgetItem(inheritTree->topLevelItem(OPTIONS_ROW), QStringList(category.getName()));
            // Allowing Tristate, this item will automatically change its state acording to its childs
            catItem->setFlags(catItem->flags() | Qt::ItemIsTristate);
            catItem->setData(0, Qt::UserRole, QVariant(key));
            catItem->setCheckState(0, Qt::Unchecked); // Make the checkbox visible by setting the default value
            inheritTree->expandItem(catItem);

            // Add the category to the combo box so we can choose it
            optionCategories->addItem(category.getName(), QVariant(key));
        }
        QList<int> settings;
        settings << -1 << -1 << -1;
        inheritedCategoriesData->insert(key, settings);

        inheritTree->expandItem(inheritTree->topLevelItem(CATEGORY_ROW)->child(category.type));
        return true;
    } else
        return false;
}

bool InheritedManager::addColumn(const Column &column, const QString &key) {
    if(unitTree && StructManager::addColumn(column, key)) {
        int index = unitTree->headerItem()->columnCount();
        unitTree->headerItem()->setText(index, column.getName());
        unitTree->headerItem()->setData(index, Qt::UserRole, QVariant(key));
        unitTree->resizeColumnToContents(unitTree->columnCount() -1);
        return true;
    } else
        return false;
}

bool InheritedManager::addProperty(const GameProperty &property, const QString &key) {
    if(StructManager::addProperty(property, key)) {
        propertyList << key;
        return true;
    } else
        return false;
}

bool InheritedManager::addOption(const UnitOption &option, const QString &key) {
    if(inheritTree && inheritedOptionsData && StructManager::addOption(option, key)) {
        QTreeWidgetItem *parent = inheritTree->topLevelItem(OPTIONS_ROW)->child(0); // Default to "No category" item
        if(!option.category.isEmpty()) {
            for(int i = 1; i<inheritTree->topLevelItem(OPTIONS_ROW)->childCount(); ++i){
                if(option.category == inheritTree->topLevelItem(OPTIONS_ROW)->child(i)->data(0, Qt::UserRole).toString()) {
                    parent = inheritTree->topLevelItem(OPTIONS_ROW)->child(i);
                    break;
                }
            }
        }
        NewTreeWidgetItem *item = new NewTreeWidgetItem(parent, QStringList(option.getName()));
        item->setData(0, Qt::UserRole, QVariant(key));
        item->setCheckState(0, Qt::Unchecked);

        inheritedOptionsData->insert(key, -1);
        inheritTree->expandItem(inheritTree->topLevelItem(OPTIONS_ROW));

        return true;
    } else
        return false;
}

bool InheritedManager::addItem(const GameItem &item, const QString &key) {
    if(inheritTree && inheritedItemsData && StructManager::addItem(item, key)) {
        QTreeWidgetItem *parent = inheritTree->topLevelItem(ITEMS_ROW)->child(0); // Default to "No category" item
        if(!item.category.isEmpty()) {
            for(int i = 1; i<inheritTree->topLevelItem(ITEMS_ROW)->childCount(); ++i){
                if(item.category == inheritTree->topLevelItem(ITEMS_ROW)->child(i)->data(0, Qt::UserRole).toString()) {
                    parent = inheritTree->topLevelItem(ITEMS_ROW)->child(i);
                    break;
                }
            }
        }

        NewTreeWidgetItem *treeItem = new NewTreeWidgetItem(parent, QStringList(item.getName()));
        treeItem->setData(0, Qt::UserRole, QVariant(key));
        treeItem->setCheckState(0, Qt::Unchecked);

        QList<int> settings;
        settings << -1 << -1;
        inheritedItemsData->insert(key, settings);
        inheritTree->expandItem(inheritTree->topLevelItem(ITEMS_ROW));

        return true;
    } else
        return false;
}

bool InheritedManager::addGlobalText(const GlobalText &globalText, const QString &key) {
    if(inheritTree && StructManager::addGlobalText(globalText, key)) {
        NewTreeWidgetItem *item = new NewTreeWidgetItem(inheritTree->topLevelItem(GLOBAL_TEXTS_ROW), QStringList(globalText.getName()));
        item->setData(0, Qt::UserRole, QVariant(key));
        item->setCheckState(0, Qt::Unchecked);
        inheritTree->expandItem(inheritTree->topLevelItem(GLOBAL_TEXTS_ROW));
        return true;
    } else
        return false;
}

void InheritedManager::removeAll() {
    if(inheritTree) {
        if(unitTree) {
            // Categories
            if(categories && itemTree && optionTree && inheritedCategoriesData &&
                    itemCategories && optionCategories && unitCategories) {
                for(int i = 0; i<inheritTree->topLevelItem(CATEGORY_ROW)->childCount(); ++i) {
                    for(int a = inheritTree->topLevelItem(CATEGORY_ROW)->child(i)->childCount() -1; a>=0; --a) {
                        QTreeWidgetItem* item = inheritTree->topLevelItem(CATEGORY_ROW)->child(i)->child(a);
                        QString key = item->data(0, Qt::UserRole).toString();
                        const GameCategory &category = categories->value(key);

                        // Delete every item associated

                        if(category.type == GameCategory::CategoryOfUnits)
                        {
                            removeCategoryItem(unitTree, a+1, key);
                            if(unitCategories->itemData(a+1).toString() == key)
                                unitCategories->removeItem(a+1);

                        } else if(category.type == GameCategory::CategoryOfItems) {
                            removeCategoryItem(itemTree, a+1, key);
                            removeCategoryItem(inheritTree->topLevelItem(ITEMS_ROW), a+1, key);
                            if(itemCategories->itemData(a+1, Qt::UserRole).toString() == key)
                                itemCategories->removeItem(a+1);

                        } else if(category.type == GameCategory::CategoryOfOptions) {
                            removeCategoryItem(optionTree, a+1, key);
                            removeCategoryItem(inheritTree->topLevelItem(OPTIONS_ROW), a+1, key);
                            if(optionCategories->itemData(a+1, Qt::UserRole).toString() == key)
                                optionCategories->removeItem(a+1);
                        }

                        delete item;

                        // Remove from QHash

                        StructManager::removeCategory(key);
                        inheritedCategoriesData->remove(key);
                    }
                }
            }

            // Columns

            if(columns) {
                int columnCount = 0;
                for(int i = 0; i<unitTree->headerItem()->columnCount(); ++i) {
                    QString key = unitTree->headerItem()->data(i, Qt::UserRole).toString();
                    if(key.isEmpty()) // It is a default column
                        columnCount = i+1;
                    else // Column added by user, remove it
                        removeColumn(key);
                }
                unitTree->setColumnCount(columnCount);
            }
        }

        // Properties

        if(properties) {
            for(int i = 0; i<propertyList.count(); ++i)
                removeProperty(propertyList.at(i));
            propertyList.clear();
        }

        // Items

        if(inheritedItemsData) {
            for(int a = 0; a<inheritTree->topLevelItem(ITEMS_ROW)->childCount(); ++a) {
                for(int i = inheritTree->topLevelItem(ITEMS_ROW)->child(a)->childCount() -1; i>=0; --i) {
                    QTreeWidgetItem *item = inheritTree->topLevelItem(ITEMS_ROW)->child(a)->child(i);
                    QString key = item->data(0, Qt::UserRole).toString();

                    // If it is checked, we must remove it from the 'global' collection
                    if(inheritanceManager && item->checkState(0) == Qt::Checked)
                        inheritanceManager->removeItem(key);

                    if(StructManager::removeItem(key)) {
                        delete item;
                        inheritedItemsData->remove(key);
                    }
                }
            }
        }

        // Options

        if(inheritedOptionsData) {
            for(int a = 0; a<inheritTree->topLevelItem(OPTIONS_ROW)->childCount(); ++a) {
                for(int i = inheritTree->topLevelItem(OPTIONS_ROW)->child(a)->childCount() -1; i>=0; --i) {
                    QTreeWidgetItem *item = inheritTree->topLevelItem(OPTIONS_ROW)->child(a)->child(i);
                    QString key = item->data(0, Qt::UserRole).toString();

                    // If it is checked, we must remove it from the 'global' collection
                    if(inheritanceManager && item->checkState(0) == Qt::Checked)
                        inheritanceManager->removeOption(key);

                    if(StructManager::removeOption(key)) {
                        delete item;
                        inheritedOptionsData->remove(key);
                    }
                }
            }
        }



        // Global texts

        if(globalTexts) {
            for(int i = inheritTree->topLevelItem(GLOBAL_TEXTS_ROW)->childCount() -1; i>=0; --i) {
                QTreeWidgetItem *item = inheritTree->topLevelItem(GLOBAL_TEXTS_ROW)->child(i);
                QString key = item->data(0, Qt::UserRole).toString();

                // If it is checked, we must remove it from the 'global' collection
                if(inheritanceManager && item->checkState(0) == Qt::Checked)
                    inheritanceManager->removeGlobalText(key);

                globalTexts->remove(key);
                delete item;
            }
        }
    }
}

void InheritedManager::removeCategoryItem(QTreeWidget *tree, int index, const QString& key) {
    if(tree) {
        QTreeWidgetItem* catItem = tree->topLevelItem(index);
        if(catItem && catItem->data(0, Qt::UserRole).toString() == key) {
            // Move all childs to "No category"
            for(int a = catItem->childCount(); a>=0;--a) {
                QTreeWidgetItem *itemToMove = catItem->child(a);
                catItem->removeChild(itemToMove);
                tree->topLevelItem(0)->addChild(itemToMove);
            }
            delete catItem;
        }
    }
}

void InheritedManager::removeCategoryItem(QTreeWidgetItem *parent, int index, const QString& key) {
    if(parent) {
        QTreeWidgetItem* catItem = parent->child(index);
        if(catItem && catItem->data(0, Qt::UserRole).toString() == key) {
            // Move all childs to "No category"
            for(int a = catItem->childCount(); a>=0;--a) {
                QTreeWidgetItem *itemToMove = catItem->child(a);
                catItem->removeChild(itemToMove);
                parent->child(0)->addChild(itemToMove);
            }
            delete catItem;
        }
    }
}

void InheritedManager::setInheritTree(QTreeWidget *inheritTree) {
    this->inheritTree = inheritTree;
}

void InheritedManager::setUnitTree(QTreeWidget *unitTree) {
    this->unitTree = unitTree;
}

void InheritedManager::setItemTree(QTreeWidget *itemTree) {
    this->itemTree = itemTree;
}

void InheritedManager::setOptionTree(QTreeWidget *optionTree) {
    this->optionTree = optionTree;
}

void InheritedManager::setOptionCategories(QComboBox *optionCategories) {
    this->optionCategories = optionCategories;
}

void InheritedManager::setItemCategories(QComboBox *itemCategories) {
    this->itemCategories = itemCategories;
}

void InheritedManager::setUnitCategories(QComboBox *unitCategories) {
    this->unitCategories = unitCategories;
}

void InheritedManager::setCategoryData(QHash<QString, QList<int> > *inheritedCategoriesData) {
    this->inheritedCategoriesData = inheritedCategoriesData;
}

void InheritedManager::setItemData(QHash<QString, QList<int> > *inheritedItemsData) {
    this->inheritedItemsData = inheritedItemsData;
}

void InheritedManager::setOptionData(QHash<QString, int> *inheritedOptionsData) {
    this->inheritedOptionsData = inheritedOptionsData;
}

void InheritedManager::setInheritanceManager(StructManager *inheritanceManager) {
    this->inheritanceManager = inheritanceManager;
}
